﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mongaba.Core.ServiceContracts;
using System.ServiceModel;
using Mongaba.Core.Registers;
using Mongaba.Core.DataContracts;
using Mongaba.Core.Enumerators;
using Mongaba.Core.Listeners;

namespace Mongaba.Core.Factory
{
    internal class CoordinatorFactory
    {
        static ServiceHost svcHost;
        public static IMongabaCoordinator Current
        {
            get;
            set;
        }

        public static CoordinatorContract CurrentContract
        {
            get;
            set;
        }
        public static IMongabaCoordinator GetLocalInstance()
        {
            if (svcHost != null)
            {
                return (IMongabaCoordinator)svcHost.SingletonInstance;
            }

            return null;
        }
     
        public static void RemoveRemoteInstanceConnection(string address)
        {
            Console.WriteLine(String.Format("Desconectando-se de {0}",address));
            try
            {
                if (remoteCoordinatorInstances.ContainsKey(address))
                {
                    (remoteCoordinatorInstances[address] as IClientChannel).Close();
                    remoteCoordinatorChannelFactoryInstances[address].Close();
                }
            }
            finally {
                remoteCoordinatorInstances.Remove(address);
                remoteCoordinatorChannelFactoryInstances.Remove(address);
            }
           
        }
        static Dictionary<string, IMongabaCoordinator> remoteCoordinatorInstances = new Dictionary<string, IMongabaCoordinator>();
        static Dictionary<string, ChannelFactory<IMongabaCoordinator>> remoteCoordinatorChannelFactoryInstances = new Dictionary<string, ChannelFactory<IMongabaCoordinator>>();


        public static IMongabaCoordinator GetRemoteInstance(string address)
        {
            Console.WriteLine(String.Format("Conectando-se a {0}", address));
            if (remoteCoordinatorInstances.ContainsKey(address))
            {
                RemoveRemoteInstanceConnection(address);
            }

            ChannelFactory<IMongabaCoordinator> factory = new ChannelFactory<IMongabaCoordinator>(BindingCreator.CreateNewTcpBinding(address.Replace(".", "")), Utilities.generateCoordinatorEndPointAddress(address));
            
            IMongabaCoordinator proxy = factory.CreateChannel();
            remoteCoordinatorInstances.Add(address, proxy);
            remoteCoordinatorChannelFactoryInstances.Add(address, factory);
            
            return proxy;
        }

        public static void StartLocalInstance(GroupContract group)
        {
            if (svcHost == null)
            {
                MongabaCoordinator mc = new MongabaCoordinator(group);
                svcHost = new ServiceHost(mc, Utilities.generateCoordinatorEndPointAddress(Utilities.HostIp.ToString()).Uri);
                svcHost.Description.Endpoints.Clear();
                BindingCreator.CreateCoordinatorBinding();
                svcHost.OpenTimeout = TimeSpan.FromDays(2);
                svcHost.CloseTimeout = TimeSpan.FromSeconds(1);
                svcHost.AddServiceEndpoint(typeof(IMongabaCoordinator), BindingCreator.GetCoordinatorBinding(), "");
                svcHost.Open();
                mc.Start();
                Current = mc;
                CurrentContract = mc.getContract();
                Console.WriteLine("A instância do coordenador local foi iniciada.");
            }
            else
            {
                MongabaCoordinator mc = (svcHost.SingletonInstance as MongabaCoordinator);
                mc.Start();
                Current = mc;
                CurrentContract = mc.getContract();
            }
        }


        public static bool IsStarted
        {
            get {
                return svcHost != null && GetLocalInstance().getStatus() != CoordinatorStatus.Sleeping;
            
            }
        }


        public static void StopLocalInstance()
        {
            if (svcHost != null)
            {
                (svcHost.SingletonInstance as MongabaCoordinator).Stop();
                svcHost.Close(TimeSpan.FromSeconds(1));
                svcHost = null;
                Console.WriteLine("A instância do coordenador local foi finalizada.");
            }          
        }



    }
}
